/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * MainFrame.java
 *
 * Created on 2010-04-25, 19:40:25
 */
package piotrrr.thesis.gui;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.JFileChooser;
import javax.swing.JTextArea;

import javax.swing.UIManager;
import piotrrr.thesis.bots.AppConfig;
import piotrrr.thesis.bots.botbase.BotBase;
import piotrrr.thesis.bots.referencebot.ReferenceBot;
import piotrrr.thesis.bots.rlbot.RLBot;

import piotrrr.thesis.bots.smartbot.SmartBot;
import piotrrr.thesis.bots.mapbotbase.MapBotBase;
import piotrrr.thesis.common.CommFun;
import piotrrr.thesis.common.GameObject;
import piotrrr.thesis.common.jobs.GlobalKillsStatsJob;
import piotrrr.thesis.common.jobs.DebugStepJob;
import piotrrr.thesis.common.stats.BotStatistic;
import piotrrr.thesis.common.stats.StatsChartsFactory;

import piotrrr.thesis.tools.Dbg;
import soc.qase.tools.vecmath.Vector3f;

/**
 *
 * @author piotrrr
 */
public class MainFrame extends javax.swing.JFrame {

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    /** Creates new form MainFrame */
    public MainFrame() {
        initComponents();
        setUpdater();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        infoButtonGroup = new javax.swing.ButtonGroup();
        jLayeredPane1 = new javax.swing.JLayeredPane();
        jTabbedPane1 = new javax.swing.JTabbedPane();
        jPanel7 = new javax.swing.JPanel();
        panelRunBots = new javax.swing.JPanel();
        nrBotsField = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        connectOthersButton = new javax.swing.JButton();
        jPanel9 = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        connectedBotsList1 = new javax.swing.JList();
        jScrollPane3 = new javax.swing.JScrollPane();
        selectedBotInfoTextArea1 = new javax.swing.JTextArea();
        jLabel4 = new javax.swing.JLabel();
        disconnectSelectedButton1 = new javax.swing.JButton();
        jPanel11 = new javax.swing.JPanel();
        connectDebugedButton = new javax.swing.JButton();
        jPanel12 = new javax.swing.JPanel();
        jLabel5 = new javax.swing.JLabel();
        nrOfSmartBotsTextField2 = new javax.swing.JTextField();
        jLabel8 = new javax.swing.JLabel();
        connectSmartBotsjButton1 = new javax.swing.JButton();
        jPanel14 = new javax.swing.JPanel();
        jLabel9 = new javax.swing.JLabel();
        nrOfRLtBotsTextField3 = new javax.swing.JTextField();
        jLabel10 = new javax.swing.JLabel();
        connectRLBotsjButton2 = new javax.swing.JButton();
        jPanel15 = new javax.swing.JPanel();
        quakePathjTextField2 = new javax.swing.JTextField();
        jLabel11 = new javax.swing.JLabel();
        jLabel12 = new javax.swing.JLabel();
        botMapsPathjTextField3 = new javax.swing.JTextField();
        jLabel13 = new javax.swing.JLabel();
        serverIPjTextField4 = new javax.swing.JTextField();
        jButton3 = new javax.swing.JButton();
        jButton4 = new javax.swing.JButton();
        applyConfigButton = new javax.swing.JButton();
        jPanel6 = new javax.swing.JPanel();
        jPanel5 = new javax.swing.JPanel();
        messagesScrollPane1 = new javax.swing.JScrollPane();
        messages = new javax.swing.JTextArea();
        jPanel2 = new javax.swing.JPanel();
        jPanel3 = new javax.swing.JPanel();
        allEntsRadioButton1 = new javax.swing.JRadioButton();
        visibleWaypointsRadioButton2 = new javax.swing.JRadioButton();
        navPlanRadioButton = new javax.swing.JRadioButton();
        visibleEntsRadioButton2 = new javax.swing.JRadioButton();
        pickupFailuresRadioButton1 = new javax.swing.JRadioButton();
        edgeFailuresRadioButton = new javax.swing.JRadioButton();
        enemyInfoRadioButton1 = new javax.swing.JRadioButton();
        jPanel8 = new javax.swing.JPanel();
        fullInfoScrollPane3 = new javax.swing.JScrollPane();
        fullInfo = new javax.swing.JTextArea();
        goToButton = new javax.swing.JButton();
        jLabel3 = new javax.swing.JLabel();
        distanceLabel = new javax.swing.JLabel();
        jPanel10 = new javax.swing.JPanel();
        reqListScrollPane2 = new javax.swing.JScrollPane();
        reqList = new javax.swing.JList();
        jPanel1 = new javax.swing.JPanel();
        pauseToggleButton = new javax.swing.JToggleButton();
        pauseAnotherBotsToggle = new javax.swing.JToggleButton();
        jTextField1 = new javax.swing.JTextField();
        sendCommandToDBGButton = new javax.swing.JButton();
        jLabel6 = new javax.swing.JLabel();
        sendCommandToAnothersButton = new javax.swing.JButton();
        stepSizeTextField2 = new javax.swing.JTextField();
        jLabel7 = new javax.swing.JLabel();
        stepButton1 = new javax.swing.JButton();
        jPanel4 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        botStateInfoTextArea1 = new javax.swing.JTextArea();
        jPanel16 = new javax.swing.JPanel();
        jPanel17 = new javax.swing.JPanel();
        jScrollPane5 = new javax.swing.JScrollPane();
        mapsList = new javax.swing.JList();
        jLabel16 = new javax.swing.JLabel();
        jLabel17 = new javax.swing.JLabel();
        jScrollPane6 = new javax.swing.JScrollPane();
        bot1List = new javax.swing.JList();
        jScrollPane7 = new javax.swing.JScrollPane();
        bot2List = new javax.swing.JList();
        jLabel18 = new javax.swing.JLabel();
        jScrollPane8 = new javax.swing.JScrollPane();
        nrOfGamesList = new javax.swing.JList();
        jLabel19 = new javax.swing.JLabel();
        startExperimentButton = new javax.swing.JButton();
        jPanel13 = new javax.swing.JPanel();
        refreshButton = new javax.swing.JButton();
        jTabbedPane2 = new javax.swing.JTabbedPane();
        killsPanel14 = new javax.swing.JPanel();
        killsByTypejPanel14 = new javax.swing.JPanel();
        deathsByTypejPanel14 = new javax.swing.JPanel();
        weaponsjPanel14 = new javax.swing.JPanel();
        whoKillsWhomjPanel14 = new javax.swing.JPanel();
        killsePerDeathjPanel14 = new javax.swing.JPanel();
        rewardPanel16 = new javax.swing.JPanel();
        avgRewardjPanel16 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jScrollPane4 = new javax.swing.JScrollPane();
        statsInfo = new javax.swing.JTextArea();
        jLabel14 = new javax.swing.JLabel();
        jLabel15 = new javax.swing.JLabel();
        statsSourcejLabel16 = new javax.swing.JLabel();
        jButton5 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Bot Debugging");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        panelRunBots.setBorder(javax.swing.BorderFactory.createTitledBorder("Connect Reference bots"));

        nrBotsField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        nrBotsField.setText("3");

        jLabel1.setText("Connect");

        jLabel2.setText("ReferenceBots");

        connectOthersButton.setText("Connect them!");
        connectOthersButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectOthersButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout panelRunBotsLayout = new javax.swing.GroupLayout(panelRunBots);
        panelRunBots.setLayout(panelRunBotsLayout);
        panelRunBotsLayout.setHorizontalGroup(
            panelRunBotsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelRunBotsLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(nrBotsField, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(connectOthersButton))
        );
        panelRunBotsLayout.setVerticalGroup(
            panelRunBotsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelRunBotsLayout.createSequentialGroup()
                .addGroup(panelRunBotsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(nrBotsField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1)
                    .addComponent(jLabel2)
                    .addComponent(connectOthersButton))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel9.setBorder(javax.swing.BorderFactory.createTitledBorder("Connected bots"));

        connectedBotsList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                connectedBotsList1ValueChanged(evt);
            }
        });
        jScrollPane2.setViewportView(connectedBotsList1);

        selectedBotInfoTextArea1.setColumns(20);
        selectedBotInfoTextArea1.setRows(5);
        jScrollPane3.setViewportView(selectedBotInfoTextArea1);

        jLabel4.setText("Selected bot info:");

        disconnectSelectedButton1.setText("Disconnect selected bot");
        disconnectSelectedButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                disconnectSelectedButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel9Layout = new javax.swing.GroupLayout(jPanel9);
        jPanel9.setLayout(jPanel9Layout);
        jPanel9Layout.setHorizontalGroup(
            jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel9Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(disconnectSelectedButton1)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 157, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel4)
                    .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 236, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel9Layout.setVerticalGroup(
            jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel9Layout.createSequentialGroup()
                .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(jPanel9Layout.createSequentialGroup()
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 257, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(disconnectSelectedButton1))
                    .addGroup(jPanel9Layout.createSequentialGroup()
                        .addComponent(jLabel4)
                        .addGap(12, 12, 12)
                        .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE)))
                .addContainerGap())
        );

        jPanel11.setBorder(javax.swing.BorderFactory.createTitledBorder("Connect debugged bot"));

        connectDebugedButton.setText("Connect debuged bot");
        connectDebugedButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectDebugedButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel11Layout = new javax.swing.GroupLayout(jPanel11);
        jPanel11.setLayout(jPanel11Layout);
        jPanel11Layout.setHorizontalGroup(
            jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel11Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(connectDebugedButton)
                .addContainerGap(248, Short.MAX_VALUE))
        );
        jPanel11Layout.setVerticalGroup(
            jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel11Layout.createSequentialGroup()
                .addComponent(connectDebugedButton)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel12.setBorder(javax.swing.BorderFactory.createTitledBorder("Connect SmartBots"));

        jLabel5.setText("Connect");

        nrOfSmartBotsTextField2.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        nrOfSmartBotsTextField2.setText("3");
        nrOfSmartBotsTextField2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nrOfSmartBotsTextField2ActionPerformed(evt);
            }
        });

        jLabel8.setText("SmartBots");

        connectSmartBotsjButton1.setText("Connect them!");
        connectSmartBotsjButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectSmartBotsjButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel12Layout = new javax.swing.GroupLayout(jPanel12);
        jPanel12.setLayout(jPanel12Layout);
        jPanel12Layout.setHorizontalGroup(
            jPanel12Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel12Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel5)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(nrOfSmartBotsTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 51, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jLabel8)
                .addGap(18, 18, 18)
                .addComponent(connectSmartBotsjButton1)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel12Layout.setVerticalGroup(
            jPanel12Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel12Layout.createSequentialGroup()
                .addGroup(jPanel12Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel5)
                    .addComponent(nrOfSmartBotsTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel8)
                    .addComponent(connectSmartBotsjButton1))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel14.setBorder(javax.swing.BorderFactory.createTitledBorder("Connect RLBots"));

        jLabel9.setText("Connect");

        nrOfRLtBotsTextField3.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        nrOfRLtBotsTextField3.setText("2");
        nrOfRLtBotsTextField3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nrOfRLtBotsTextField3ActionPerformed(evt);
            }
        });

        jLabel10.setText("RLBots");

        connectRLBotsjButton2.setText("Connect them!");
        connectRLBotsjButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectRLBotsjButton2ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel14Layout = new javax.swing.GroupLayout(jPanel14);
        jPanel14.setLayout(jPanel14Layout);
        jPanel14Layout.setHorizontalGroup(
            jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel14Layout.createSequentialGroup()
                .addContainerGap(120, Short.MAX_VALUE)
                .addComponent(jLabel9)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(nrOfRLtBotsTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, 51, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jLabel10)
                .addGap(34, 34, 34)
                .addComponent(connectRLBotsjButton2))
        );
        jPanel14Layout.setVerticalGroup(
            jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel14Layout.createSequentialGroup()
                .addGroup(jPanel14Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel9)
                    .addComponent(nrOfRLtBotsTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel10)
                    .addComponent(connectRLBotsjButton2))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel15.setBorder(javax.swing.BorderFactory.createTitledBorder("Config"));

        quakePathjTextField2.setText("H:\\workspace\\inzynierka\\testing-env\\quake2-3_21\\quake2");
        quakePathjTextField2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                quakePathjTextField2ActionPerformed(evt);
            }
        });

        jLabel11.setText("Quake path:");

        jLabel12.setText("Bot maps path:");

        botMapsPathjTextField3.setText("H:\\workspace\\inzynierka\\SmartBot\\botmaps");
        botMapsPathjTextField3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botMapsPathjTextField3ActionPerformed(evt);
            }
        });

        jLabel13.setText("Server IP");

        serverIPjTextField4.setText("127.0.0.1");
        serverIPjTextField4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                serverIPjTextField4ActionPerformed(evt);
            }
        });

        jButton3.setText("Browse");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        jButton4.setText("Browse");
        jButton4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton4ActionPerformed(evt);
            }
        });

        applyConfigButton.setText("Apply config");
        applyConfigButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                applyConfigButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel15Layout = new javax.swing.GroupLayout(jPanel15);
        jPanel15.setLayout(jPanel15Layout);
        jPanel15Layout.setHorizontalGroup(
            jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel15Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(jPanel15Layout.createSequentialGroup()
                            .addGroup(jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(jButton4, javax.swing.GroupLayout.Alignment.TRAILING)
                                .addGroup(jPanel15Layout.createSequentialGroup()
                                    .addComponent(jLabel12)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(botMapsPathjTextField3, javax.swing.GroupLayout.DEFAULT_SIZE, 174, Short.MAX_VALUE))
                                .addGroup(jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                    .addComponent(jButton3)
                                    .addGroup(jPanel15Layout.createSequentialGroup()
                                        .addComponent(jLabel11)
                                        .addGap(18, 18, 18)
                                        .addComponent(quakePathjTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 173, javax.swing.GroupLayout.PREFERRED_SIZE))))
                            .addGap(22, 22, 22))
                        .addGroup(jPanel15Layout.createSequentialGroup()
                            .addGroup(jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addGroup(jPanel15Layout.createSequentialGroup()
                                    .addGap(77, 77, 77)
                                    .addComponent(serverIPjTextField4, javax.swing.GroupLayout.PREFERRED_SIZE, 85, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addComponent(jLabel13))
                            .addContainerGap(111, Short.MAX_VALUE)))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel15Layout.createSequentialGroup()
                        .addComponent(applyConfigButton)
                        .addContainerGap())))
        );
        jPanel15Layout.setVerticalGroup(
            jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel15Layout.createSequentialGroup()
                .addGroup(jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel11)
                    .addComponent(quakePathjTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton3)
                .addGap(19, 19, 19)
                .addGroup(jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel12)
                    .addComponent(botMapsPathjTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jButton4)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel13)
                    .addComponent(serverIPjTextField4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(applyConfigButton)
                .addContainerGap())
        );

        javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
        jPanel7.setLayout(jPanel7Layout);
        jPanel7Layout.setHorizontalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(jPanel7Layout.createSequentialGroup()
                            .addComponent(jPanel12, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(jPanel14, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addGroup(jPanel7Layout.createSequentialGroup()
                            .addComponent(panelRunBots, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(jPanel11, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                    .addGroup(jPanel7Layout.createSequentialGroup()
                        .addComponent(jPanel9, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jPanel15, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addGap(310, 310, 310))
        );
        jPanel7Layout.setVerticalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel7Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(panelRunBots, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jPanel11, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel14, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel12, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel9, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jPanel15, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(130, Short.MAX_VALUE))
        );

        jTabbedPane1.addTab("Connect bots", jPanel7);

        jPanel5.setBorder(javax.swing.BorderFactory.createTitledBorder("Messages"));

        messages.setColumns(20);
        messages.setRows(5);
        messagesScrollPane1.setViewportView(messages);

        javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
        jPanel5.setLayout(jPanel5Layout);
        jPanel5Layout.setHorizontalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(messagesScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 729, Short.MAX_VALUE)
                .addContainerGap())
        );
        jPanel5Layout.setVerticalGroup(
            jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel5Layout.createSequentialGroup()
                .addComponent(messagesScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 83, Short.MAX_VALUE)
                .addContainerGap())
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Bot world info"));

        jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Display info options"));

        infoButtonGroup.add(allEntsRadioButton1);
        allEntsRadioButton1.setSelected(true);
        allEntsRadioButton1.setText("all entities in the WorldKB");
        allEntsRadioButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                allEntsRadioButton1ActionPerformed(evt);
            }
        });

        infoButtonGroup.add(visibleWaypointsRadioButton2);
        visibleWaypointsRadioButton2.setText("visible waypoints");
        visibleWaypointsRadioButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                visibleWaypointsRadioButton2ActionPerformed(evt);
            }
        });

        infoButtonGroup.add(navPlanRadioButton);
        navPlanRadioButton.setText("navigation plan details");
        navPlanRadioButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                navPlanRadioButtonActionPerformed(evt);
            }
        });

        infoButtonGroup.add(visibleEntsRadioButton2);
        visibleEntsRadioButton2.setText("visible entities");
        visibleEntsRadioButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                visibleEntsRadioButton2ActionPerformed(evt);
            }
        });

        infoButtonGroup.add(pickupFailuresRadioButton1);
        pickupFailuresRadioButton1.setText("pickup failures");
        pickupFailuresRadioButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                pickupFailuresRadioButton1ActionPerformed(evt);
            }
        });

        infoButtonGroup.add(edgeFailuresRadioButton);
        edgeFailuresRadioButton.setText("edge failures");
        edgeFailuresRadioButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                edgeFailuresRadioButtonActionPerformed(evt);
            }
        });

        infoButtonGroup.add(enemyInfoRadioButton1);
        enemyInfoRadioButton1.setText("enemy information");
        enemyInfoRadioButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                enemyInfoRadioButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(visibleWaypointsRadioButton2)
                    .addComponent(pickupFailuresRadioButton1)
                    .addComponent(allEntsRadioButton1)
                    .addComponent(visibleEntsRadioButton2)
                    .addComponent(navPlanRadioButton)
                    .addComponent(edgeFailuresRadioButton)
                    .addComponent(enemyInfoRadioButton1))
                .addContainerGap())
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(allEntsRadioButton1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(visibleEntsRadioButton2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(visibleWaypointsRadioButton2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(pickupFailuresRadioButton1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(navPlanRadioButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(edgeFailuresRadioButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(enemyInfoRadioButton1)
                .addContainerGap(63, Short.MAX_VALUE))
        );

        jPanel8.setBorder(javax.swing.BorderFactory.createTitledBorder("Full information on selected item"));

        fullInfo.setColumns(20);
        fullInfo.setRows(5);
        fullInfoScrollPane3.setViewportView(fullInfo);

        goToButton.setText("Go to this position");
        goToButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                goToButtonActionPerformed(evt);
            }
        });

        jLabel3.setText("Distance from the bot:");

        distanceLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        distanceLabel.setText("0");

        javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8);
        jPanel8.setLayout(jPanel8Layout);
        jPanel8Layout.setHorizontalGroup(
            jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel8Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(fullInfoScrollPane3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 348, Short.MAX_VALUE)
                    .addGroup(jPanel8Layout.createSequentialGroup()
                        .addComponent(jLabel3)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(distanceLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 62, Short.MAX_VALUE)
                        .addComponent(goToButton, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        jPanel8Layout.setVerticalGroup(
            jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel8Layout.createSequentialGroup()
                .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(distanceLabel)
                    .addComponent(goToButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(fullInfoScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE)
                .addContainerGap())
        );

        jPanel10.setBorder(javax.swing.BorderFactory.createTitledBorder("Info items list"));

        reqList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        reqList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                reqListValueChanged(evt);
            }
        });
        reqListScrollPane2.setViewportView(reqList);

        javax.swing.GroupLayout jPanel10Layout = new javax.swing.GroupLayout(jPanel10);
        jPanel10.setLayout(jPanel10Layout);
        jPanel10Layout.setHorizontalGroup(
            jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel10Layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(reqListScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        jPanel10Layout.setVerticalGroup(
            jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel10Layout.createSequentialGroup()
                .addComponent(reqListScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 220, Short.MAX_VALUE)
                .addContainerGap())
        );

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel10, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(jPanel8, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel10, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Bot control"));

        pauseToggleButton.setText("Pause dbg bot");
        pauseToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                pauseToggleButtonActionPerformed(evt);
            }
        });

        pauseAnotherBotsToggle.setText("Pause other bots");
        pauseAnotherBotsToggle.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                pauseAnotherBotsToggleActionPerformed(evt);
            }
        });

        jTextField1.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        jTextField1.setText("disc");

        sendCommandToDBGButton.setText("<html><center>send cmd <br> to dbg");
        sendCommandToDBGButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sendCommandToDBGButtonActionPerformed(evt);
            }
        });

        jLabel6.setText("Command: ");

        sendCommandToAnothersButton.setText("<html><center>send cmd <br> to others");
        sendCommandToAnothersButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sendCommandToAnothersButtonActionPerformed(evt);
            }
        });

        stepSizeTextField2.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        stepSizeTextField2.setText("10");

        jLabel7.setText("Step size:");

        stepButton1.setText("step");
        stepButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stepButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(pauseToggleButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(pauseAnotherBotsToggle))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanel1Layout.createSequentialGroup()
                                .addComponent(jLabel7)
                                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addGroup(jPanel1Layout.createSequentialGroup()
                                        .addGap(95, 95, 95)
                                        .addComponent(sendCommandToAnothersButton))
                                    .addGroup(jPanel1Layout.createSequentialGroup()
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                        .addComponent(stepSizeTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                        .addComponent(stepButton1))))
                            .addGroup(jPanel1Layout.createSequentialGroup()
                                .addComponent(jLabel6)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 61, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(sendCommandToDBGButton)))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(pauseToggleButton)
                    .addComponent(pauseAnotherBotsToggle))
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(sendCommandToAnothersButton)
                            .addComponent(sendCommandToDBGButton))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 26, Short.MAX_VALUE)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel6))
                        .addGap(19, 19, 19)))
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel7)
                    .addComponent(stepSizeTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(stepButton1))
                .addContainerGap())
        );

        jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder("Debugged bot state info"));

        botStateInfoTextArea1.setColumns(20);
        botStateInfoTextArea1.setRows(5);
        jScrollPane1.setViewportView(botStateInfoTextArea1);

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 381, Short.MAX_VALUE)
                .addContainerGap())
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 122, Short.MAX_VALUE)
                .addContainerGap())
        );

        javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
        jPanel6.setLayout(jPanel6Layout);
        jPanel6Layout.setHorizontalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel6Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel5, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(jPanel6Layout.createSequentialGroup()
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jPanel6Layout.setVerticalGroup(
            jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel6Layout.createSequentialGroup()
                .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );

        jTabbedPane1.addTab("Info & Control", jPanel6);

        jPanel17.setBorder(javax.swing.BorderFactory.createTitledBorder("Options"));

        mapsList.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "q2dm1", "map1", "map2" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        mapsList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        mapsList.setSelectedIndex(1);
        jScrollPane5.setViewportView(mapsList);

        jLabel16.setText("Map");

        jLabel17.setText("Bot1");

        bot1List.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "ReferenceBot", "RLBot", "NoRLBot" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        bot1List.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        bot1List.setSelectedIndex(0);
        jScrollPane6.setViewportView(bot1List);

        bot2List.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "ReferenceBot", "RLBot", "NoRLBot" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        bot2List.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        bot2List.setSelectedIndex(1);
        jScrollPane7.setViewportView(bot2List);

        jLabel18.setText("Bot2");

        nrOfGamesList.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "1", "2", "3", "4", "5" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        nrOfGamesList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        nrOfGamesList.setSelectedIndex(2);
        jScrollPane8.setViewportView(nrOfGamesList);

        jLabel19.setText("Nr of games");

        javax.swing.GroupLayout jPanel17Layout = new javax.swing.GroupLayout(jPanel17);
        jPanel17.setLayout(jPanel17Layout);
        jPanel17Layout.setHorizontalGroup(
            jPanel17Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel17Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel17Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane5, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel16))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel17Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel17))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel17Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel18))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel17Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jScrollPane8)
                    .addComponent(jLabel19, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel17Layout.setVerticalGroup(
            jPanel17Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel17Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel17Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(jPanel17Layout.createSequentialGroup()
                        .addComponent(jLabel19)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jPanel17Layout.createSequentialGroup()
                        .addGroup(jPanel17Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel16)
                            .addComponent(jLabel17)
                            .addComponent(jLabel18))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel17Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(jScrollPane7)
                            .addComponent(jScrollPane6)
                            .addComponent(jScrollPane5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
                .addContainerGap(17, Short.MAX_VALUE))
        );

        startExperimentButton.setText("Start");
        startExperimentButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startExperimentButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel16Layout = new javax.swing.GroupLayout(jPanel16);
        jPanel16.setLayout(jPanel16Layout);
        jPanel16Layout.setHorizontalGroup(
            jPanel16Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel16Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel16Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel17, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(startExperimentButton))
                .addContainerGap(449, Short.MAX_VALUE))
        );
        jPanel16Layout.setVerticalGroup(
            jPanel16Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel16Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel17, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(startExperimentButton)
                .addContainerGap(345, Short.MAX_VALUE))
        );

        jTabbedPane1.addTab("Run Experiment", jPanel16);

        refreshButton.setText("Refresh");
        refreshButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                refreshButtonActionPerformed(evt);
            }
        });

        killsPanel14.setLayout(new java.awt.GridLayout(1, 1, 5, 5));
        jTabbedPane2.addTab("kills by bot", killsPanel14);

        killsByTypejPanel14.setLayout(new java.awt.GridLayout(1, 0));
        jTabbedPane2.addTab("kills by bot type", killsByTypejPanel14);

        deathsByTypejPanel14.setLayout(new java.awt.GridLayout(1, 0));
        jTabbedPane2.addTab("deaths by bot type", deathsByTypejPanel14);

        weaponsjPanel14.setLayout(new java.awt.GridLayout(1, 0));
        jTabbedPane2.addTab("weapons by bot", weaponsjPanel14);

        whoKillsWhomjPanel14.setLayout(new java.awt.GridLayout(1, 0));
        jTabbedPane2.addTab("who kills whom", whoKillsWhomjPanel14);

        killsePerDeathjPanel14.setLayout(new java.awt.GridLayout(1, 0));
        jTabbedPane2.addTab("kills per death", killsePerDeathjPanel14);

        rewardPanel16.setLayout(new java.awt.GridLayout(1, 0));
        jTabbedPane2.addTab("reward", rewardPanel16);

        avgRewardjPanel16.setLayout(new java.awt.GridLayout(1, 0));
        jTabbedPane2.addTab("avg reward", avgRewardjPanel16);

        jButton1.setText("Save current statistics");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jButton2.setText("Load statistics");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        statsInfo.setColumns(20);
        statsInfo.setRows(4);
        jScrollPane4.setViewportView(statsInfo);

        jLabel14.setText("Stats info");

        jLabel15.setText("Stats source:");

        statsSourcejLabel16.setText("none");

        jButton5.setText("Load game stats");
        jButton5.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton5ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel13Layout = new javax.swing.GroupLayout(jPanel13);
        jPanel13.setLayout(jPanel13Layout);
        jPanel13Layout.setHorizontalGroup(
            jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel13Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jTabbedPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 761, Short.MAX_VALUE)
                    .addGroup(jPanel13Layout.createSequentialGroup()
                        .addGroup(jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanel13Layout.createSequentialGroup()
                                .addComponent(refreshButton)
                                .addGap(18, 18, 18)
                                .addComponent(jButton1))
                            .addComponent(jButton5))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanel13Layout.createSequentialGroup()
                                .addComponent(jButton2)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jLabel14))
                            .addGroup(jPanel13Layout.createSequentialGroup()
                                .addComponent(jLabel15)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(statsSourcejLabel16)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 321, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        jPanel13Layout.setVerticalGroup(
            jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel13Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(jPanel13Layout.createSequentialGroup()
                        .addGroup(jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(refreshButton)
                            .addComponent(jButton1)
                            .addComponent(jButton2))
                        .addGap(12, 12, 12)
                        .addGroup(jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel15)
                            .addComponent(statsSourcejLabel16)
                            .addComponent(jButton5))
                        .addGap(11, 11, 11))
                    .addGroup(jPanel13Layout.createSequentialGroup()
                        .addGroup(jPanel13Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel14)
                            .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)))
                .addComponent(jTabbedPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 505, Short.MAX_VALUE)
                .addContainerGap())
        );

        jTabbedPane1.addTab("Statistics", jPanel13);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jTabbedPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 786, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 621, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void connectDebugedButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectDebugedButtonActionPerformed
        if (dbgBot != null) {
            return;
        }
        RLBot bot = new RLBot("RLBot-dbg", AppConfig.altSkinName);
        bot.connect(AppConfig.serverIP, AppConfig.serverPort);
        stepJob = new DebugStepJob(bot, this);
        bot.addBotJob(stepJob);
        bot.addBotJob(new GlobalKillsStatsJob(bot));
        gameStats = BotStatistic.createNewInstance();
        dbgBot = bot;
    }//GEN-LAST:event_connectDebugedButtonActionPerformed

    private void connectOthersButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectOthersButtonActionPerformed
        int num = Integer.parseInt(nrBotsField.getText());
        for (int i = 0; i < num; i++) {
            ReferenceBot bot = new ReferenceBot("ReferenceBot-" + i, AppConfig.skinName);
            bot.dtalk.active = false;
            bot.connect(AppConfig.serverIP, AppConfig.serverPort);
            bots.add(bot);
        }
    }//GEN-LAST:event_connectOthersButtonActionPerformed

    private void pauseToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pauseToggleButtonActionPerformed
        dbgBot.botPaused = pauseToggleButton.isSelected();
    }//GEN-LAST:event_pauseToggleButtonActionPerformed

    private void reqListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_reqListValueChanged
        int ind = reqList.getSelectedIndex();
        if (ind < 0 || ind > requiredList.size()) {
            return;
        }
        fullInfo.setText(requiredList.get(ind).toDetailedString());
        Vector3f lookAt = new Vector3f(requiredList.get(ind).getObjectPosition());
        dbgBot.setPauseLookAtPosition(lookAt);
        distanceLabel.setText("" + CommFun.getDistanceBetweenPositions(dbgBot.getBotPosition(), requiredList.get(ind).getObjectPosition()));
    }//GEN-LAST:event_reqListValueChanged

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        updater.stop = true;
        if (dbgBot != null) {
            dbgBot.disconnect();
        }
        for (MapBotBase b : bots) {
            b.disconnect();
        }
        bots.clear();
        
        for (Process p : childProcesses) p.destroy();
        childProcesses.clear();

        AppConfig.writeConfig();
    }//GEN-LAST:event_formWindowClosing

    private void pauseAnotherBotsToggleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pauseAnotherBotsToggleActionPerformed
        for (MapBotBase b : bots) {
            b.botPaused = pauseAnotherBotsToggle.isSelected();
        }
    }//GEN-LAST:event_pauseAnotherBotsToggleActionPerformed

    private void sendCommandToDBGButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sendCommandToDBGButtonActionPerformed
        String cmd = jTextField1.getText();
        dbgBot.handleCommand(cmd);
    }//GEN-LAST:event_sendCommandToDBGButtonActionPerformed

    private void sendCommandToAnothersButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sendCommandToAnothersButtonActionPerformed
        String cmd = jTextField1.getText();
        for (MapBotBase b : bots) {
            b.handleCommand(cmd);
        }
    }//GEN-LAST:event_sendCommandToAnothersButtonActionPerformed

    private void allEntsRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allEntsRadioButton1ActionPerformed
        Vector<GameObject> v = new Vector<GameObject>();
        //FIXMe:
        v.addAll(dbgBot.kb.getAllItems());
//      v.addAll(dbgBot.kb.getAllPickableEntities());
        setReqList(v);
    }//GEN-LAST:event_allEntsRadioButton1ActionPerformed

    private void visibleWaypointsRadioButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_visibleWaypointsRadioButton2ActionPerformed
        Vector<GameObject> v = new Vector<GameObject>();
        v.addAll(dbgBot.kb.getAllVisibleWaypoints());
        setReqList(v);
    }//GEN-LAST:event_visibleWaypointsRadioButton2ActionPerformed

    private void stepButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stepButton1ActionPerformed
        int steps = Integer.parseInt(stepSizeTextField2.getText());
        stepJob.pauseIn(steps);
    }//GEN-LAST:event_stepButton1ActionPerformed

    private void navPlanRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_navPlanRadioButtonActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_navPlanRadioButtonActionPerformed

    private void visibleEntsRadioButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_visibleEntsRadioButton2ActionPerformed
        Vector<GameObject> v = new Vector<GameObject>();
        v.addAll(dbgBot.kb.getAllVisibleEntities());
        setReqList(v);
    }//GEN-LAST:event_visibleEntsRadioButton2ActionPerformed

    private void pickupFailuresRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pickupFailuresRadioButton1ActionPerformed
        Vector<GameObject> v = new Vector<GameObject>();
        v.addAll(dbgBot.kb.getAllEntsWithPickupFailure());
        setReqList(v);
    }//GEN-LAST:event_pickupFailuresRadioButton1ActionPerformed

    private void edgeFailuresRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_edgeFailuresRadioButtonActionPerformed
//    	Vector<GameObject> v = new Vector<GameObject>();
//        v.addAll(dbgBot.kb.getAllEdgeFailures());
//        setReqList(v);
    }//GEN-LAST:event_edgeFailuresRadioButtonActionPerformed

    private void goToButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_goToButtonActionPerformed
        if (reqList.getSelectedIndex() == -1) {
            return;
        }
        Vector3f dst = requiredList.elementAt(reqList.getSelectedIndex()).getObjectPosition();
        dbgBot.goToPositionWithNoClipCheating(dst);
    }//GEN-LAST:event_goToButtonActionPerformed

    private void enemyInfoRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enemyInfoRadioButton1ActionPerformed
        Vector<GameObject> v = new Vector<GameObject>();
        v.addAll(dbgBot.kb.getAllEnemyInformation());
        setReqList(v);
    }//GEN-LAST:event_enemyInfoRadioButton1ActionPerformed

    private void connectSmartBotsjButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectSmartBotsjButton1ActionPerformed
        int num = Integer.parseInt(nrOfSmartBotsTextField2.getText());
        for (int i = 0; i < num; i++) {
            SmartBot bot = new SmartBot("SmartBot-" + i, AppConfig.skinName);
            bot.dtalk.active = false;
            bot.connect(AppConfig.serverIP, AppConfig.serverPort);
            bots.add(bot);
        }
    }//GEN-LAST:event_connectSmartBotsjButton1ActionPerformed

    private void connectedBotsList1ValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_connectedBotsList1ValueChanged
        int ind = connectedBotsList1.getSelectedIndex();
        BotBase bot = getBotFromList(ind);
        if (bot == null) {
            return;
        }
        if (bot.getFrameNumber() < 2) {
            return;
        }
        selectedBotInfoTextArea1.setText(bot.toDetailedString());
    }//GEN-LAST:event_connectedBotsList1ValueChanged

    private void disconnectSelectedButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_disconnectSelectedButton1ActionPerformed
        int ind = connectedBotsList1.getSelectedIndex();
        BotBase bot = getBotFromList(ind);
        if (bot == null) {
            return;
        }
        bot.disconnect();
    }//GEN-LAST:event_disconnectSelectedButton1ActionPerformed

    private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed
        if (currentStats == null) {
            statsSourcejLabel16.setText("none");
            return;
        }
        if (currentStats == loadedStats) {
            statsSourcejLabel16.setText("from file");
        }
        if (currentStats == gameStats) {
            statsSourcejLabel16.setText("from a game");
            currentStats.statsInfo = getStatsDescription();
        }

        statsInfo.setText(currentStats.statsInfo);

        killsPanel14.removeAll();
        killsPanel14.add(StatsChartsFactory.getKillsInTimeByBot(currentStats));
        killsPanel14.revalidate();

        killsByTypejPanel14.removeAll();
        killsByTypejPanel14.add(StatsChartsFactory.getKillsInTimeByBotType(currentStats));
        killsByTypejPanel14.revalidate();

        deathsByTypejPanel14.removeAll();
        deathsByTypejPanel14.add(StatsChartsFactory.getDeathsInTimeByBotType(currentStats));
        deathsByTypejPanel14.revalidate();

        weaponsjPanel14.removeAll();
        weaponsjPanel14.add(StatsChartsFactory.getWeaponUseageByBotBarChart(currentStats));
        weaponsjPanel14.revalidate();

        killsePerDeathjPanel14.removeAll();
        killsePerDeathjPanel14.add(StatsChartsFactory.getKillsPerEachDeathByBotType(currentStats));
        killsePerDeathjPanel14.revalidate();

        whoKillsWhomjPanel14.removeAll();
        whoKillsWhomjPanel14.add(StatsChartsFactory.getWhoKillsWhomBarChart(currentStats));
        whoKillsWhomjPanel14.revalidate();

        rewardPanel16.removeAll();
        rewardPanel16.add(StatsChartsFactory.getRewardsInTimeByEachBot(currentStats));
        rewardPanel16.revalidate();

        avgRewardjPanel16.removeAll();
        avgRewardjPanel16.add(StatsChartsFactory.getAvgRewardsChart(currentStats));
        avgRewardjPanel16.revalidate();


    }//GEN-LAST:event_refreshButtonActionPerformed

    private void nrOfSmartBotsTextField2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nrOfSmartBotsTextField2ActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_nrOfSmartBotsTextField2ActionPerformed

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed

        if (currentStats == null) {
            return;
        }
        JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
        fc.setApproveButtonText("Save");
        fc.setDialogTitle("Save current statistics");
        fc.showOpenDialog(this);
        System.out.println("Saving stats to file: " + fc.getSelectedFile());
        currentStats.saveToFile(fc.getSelectedFile().getPath());

    }//GEN-LAST:event_jButton1ActionPerformed

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
        fc.setApproveButtonText("Open");
        fc.setDialogTitle("Open statistics");
        fc.showOpenDialog(this);
        System.out.println("Reading stats from file: " + fc.getSelectedFile());
        loadedStats = BotStatistic.readFromFile(fc.getSelectedFile().getPath());
        currentStats = loadedStats;
        refreshButtonActionPerformed(null);
    }//GEN-LAST:event_jButton2ActionPerformed

    private void nrOfRLtBotsTextField3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nrOfRLtBotsTextField3ActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_nrOfRLtBotsTextField3ActionPerformed

    private void connectRLBotsjButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectRLBotsjButton2ActionPerformed
        int num = Integer.parseInt(nrOfRLtBotsTextField3.getText());
        for (int i = 0; i < num; i++) {
            RLBot bot = new RLBot("RLBot-" + i, AppConfig.altSkinName);
            bot.dtalk.active = false;
            bot.connect(AppConfig.serverIP, AppConfig.serverPort);
            bots.add(bot);
        }
    }//GEN-LAST:event_connectRLBotsjButton2ActionPerformed

    private void quakePathjTextField2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_quakePathjTextField2ActionPerformed
    }//GEN-LAST:event_quakePathjTextField2ActionPerformed

    private void botMapsPathjTextField3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botMapsPathjTextField3ActionPerformed
    }//GEN-LAST:event_botMapsPathjTextField3ActionPerformed

    private void serverIPjTextField4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_serverIPjTextField4ActionPerformed
    }//GEN-LAST:event_serverIPjTextField4ActionPerformed

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
        fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        fc.setApproveButtonText("Open");
        fc.setDialogTitle("Choose Quake2 root path");
        fc.showOpenDialog(this);
        System.out.println("Q2 Path: " + fc.getSelectedFile());
        quakePathjTextField2.setText(fc.getSelectedFile().getPath());
    }//GEN-LAST:event_jButton3ActionPerformed

    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed
        JFileChooser fc = new JFileChooser(System.getProperty("user.dir"));
        fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        fc.setApproveButtonText("Open");
        fc.setDialogTitle("Choose bots maps directory path");
        fc.showOpenDialog(this);
        System.out.println("Maps Path: " + fc.getSelectedFile());
        botMapsPathjTextField3.setText(fc.getSelectedFile().getPath());
    }//GEN-LAST:event_jButton4ActionPerformed

    private void applyConfigButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_applyConfigButtonActionPerformed
        AppConfig.quakePath = quakePathjTextField2.getText();
        AppConfig.serverIP = serverIPjTextField4.getText();
        AppConfig.botMapsDir = botMapsPathjTextField3.getText() + "\\";
        System.setProperty("QUAKE2", AppConfig.quakePath);
        AppConfig.writeConfig();
    }//GEN-LAST:event_applyConfigButtonActionPerformed

    private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton5ActionPerformed
        if (gameStats == null) {
            gameStats = BotStatistic.createNewInstance();
        }
        currentStats = gameStats;
        refreshButtonActionPerformed(evt);
    }//GEN-LAST:event_jButton5ActionPerformed

    private MapBotBase connectBotByListOption(String option, int nr, int port) {
        MapBotBase bot = null;
        if (option.equals("ReferenceBot")) {
            Dbg.prn("connecting rfrnc");
            bot = new ReferenceBot(option + "-" + nr, AppConfig.skinName);

        } else if (option.equals("RLBot")) {
            Dbg.prn("connecting rlbot learing");
            bot = new RLBot(option + "-" + nr, AppConfig.altSkinName);

        } else if (option.equals("NoRLBot")) {
            Dbg.prn("connecting rlbot rubbing the mint");
            bot = new RLBot(option + "-" + nr, AppConfig.altSkinName);
            ((RLBot) bot).combatModule.brain.setAlpha(0.0);
            ((RLBot) bot).combatModule.brain.setRandActions(0.99);
        }
        bot.connect(AppConfig.serverIP, port);
        return bot;
    }

    private void runLocalQ2Server(int port, String mapName) {
        String cmd = AppConfig.quakePath + "\\quake2.exe +set dedicated 1 +set deathmatch 1 +set maxclients 32 +map "+mapName+" +set cheats 1 +set port " + port;
        String batName = "run" + port + ".bat";
        try {
            PrintWriter pw = new PrintWriter(new FileWriter(batName));
            pw.println("cd " + AppConfig.quakePath);
            pw.println(cmd);
            pw.println();
            pw.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            Process p = Runtime.getRuntime().exec(batName);
            childProcesses.add(p);
        } catch (Exception err) {
            err.printStackTrace();
        }
    }

    private void startExperimentButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startExperimentButtonActionPerformed
        int gamesNr = Integer.parseInt(nrOfGamesList.getSelectedValue().toString());
        String b1 = bot1List.getSelectedValue().toString();
        String b2 = bot2List.getSelectedValue().toString();

        String mapName = mapsList.getSelectedValue().toString();

        gameStats = BotStatistic.createNewInstance();

        for (int i = 0; i < gamesNr; i++) {
            runLocalQ2Server(AppConfig.serverPort + i, mapName);
            sleep(1000);
            MapBotBase bot1 = connectBotByListOption(b1, i, AppConfig.serverPort + i);
            bot1.addBotJob(new GlobalKillsStatsJob(bot1));
            bots.add(bot1);
            sleep(1000);
            MapBotBase bot2 = connectBotByListOption(b2, i, AppConfig.serverPort + i);
            bots.add(bot2);
            sleep(1000);
        }
        Dbg.prn("gamesNr: " + gamesNr);
    }//GEN-LAST:event_startExperimentButtonActionPerformed

    private void sleep(int milis) {
        try {
            Thread.sleep(milis);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        AppConfig.readConfig();
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception ex) {
            try {
                UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
            } catch (Exception ex1) {
                System.err.println("No look and feel available :(");
                ex1.printStackTrace();
                return;
            }
        }
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                MainFrame mf = new MainFrame();
                mf.setVisible(true);
//                Dbg.toAppend = mf.getMessagesTextArea();
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JRadioButton allEntsRadioButton1;
    private javax.swing.JButton applyConfigButton;
    private javax.swing.JPanel avgRewardjPanel16;
    private javax.swing.JList bot1List;
    private javax.swing.JList bot2List;
    private javax.swing.JTextField botMapsPathjTextField3;
    private javax.swing.JTextArea botStateInfoTextArea1;
    private javax.swing.JButton connectDebugedButton;
    private javax.swing.JButton connectOthersButton;
    private javax.swing.JButton connectRLBotsjButton2;
    private javax.swing.JButton connectSmartBotsjButton1;
    private javax.swing.JList connectedBotsList1;
    private javax.swing.JPanel deathsByTypejPanel14;
    private javax.swing.JButton disconnectSelectedButton1;
    private javax.swing.JLabel distanceLabel;
    private javax.swing.JRadioButton edgeFailuresRadioButton;
    private javax.swing.JRadioButton enemyInfoRadioButton1;
    private javax.swing.JTextArea fullInfo;
    private javax.swing.JScrollPane fullInfoScrollPane3;
    private javax.swing.JButton goToButton;
    private javax.swing.ButtonGroup infoButtonGroup;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButton4;
    private javax.swing.JButton jButton5;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel13;
    private javax.swing.JLabel jLabel14;
    private javax.swing.JLabel jLabel15;
    private javax.swing.JLabel jLabel16;
    private javax.swing.JLabel jLabel17;
    private javax.swing.JLabel jLabel18;
    private javax.swing.JLabel jLabel19;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JLayeredPane jLayeredPane1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel10;
    private javax.swing.JPanel jPanel11;
    private javax.swing.JPanel jPanel12;
    private javax.swing.JPanel jPanel13;
    private javax.swing.JPanel jPanel14;
    private javax.swing.JPanel jPanel15;
    private javax.swing.JPanel jPanel16;
    private javax.swing.JPanel jPanel17;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JPanel jPanel8;
    private javax.swing.JPanel jPanel9;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JScrollPane jScrollPane5;
    private javax.swing.JScrollPane jScrollPane6;
    private javax.swing.JScrollPane jScrollPane7;
    private javax.swing.JScrollPane jScrollPane8;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JTabbedPane jTabbedPane2;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JPanel killsByTypejPanel14;
    private javax.swing.JPanel killsPanel14;
    private javax.swing.JPanel killsePerDeathjPanel14;
    private javax.swing.JList mapsList;
    private javax.swing.JTextArea messages;
    private javax.swing.JScrollPane messagesScrollPane1;
    private javax.swing.JRadioButton navPlanRadioButton;
    private javax.swing.JTextField nrBotsField;
    private javax.swing.JList nrOfGamesList;
    private javax.swing.JTextField nrOfRLtBotsTextField3;
    private javax.swing.JTextField nrOfSmartBotsTextField2;
    private javax.swing.JPanel panelRunBots;
    private javax.swing.JToggleButton pauseAnotherBotsToggle;
    private javax.swing.JToggleButton pauseToggleButton;
    private javax.swing.JRadioButton pickupFailuresRadioButton1;
    private javax.swing.JTextField quakePathjTextField2;
    private javax.swing.JButton refreshButton;
    private javax.swing.JList reqList;
    private javax.swing.JScrollPane reqListScrollPane2;
    private javax.swing.JPanel rewardPanel16;
    private javax.swing.JTextArea selectedBotInfoTextArea1;
    private javax.swing.JButton sendCommandToAnothersButton;
    private javax.swing.JButton sendCommandToDBGButton;
    private javax.swing.JTextField serverIPjTextField4;
    private javax.swing.JButton startExperimentButton;
    private javax.swing.JTextArea statsInfo;
    private javax.swing.JLabel statsSourcejLabel16;
    private javax.swing.JButton stepButton1;
    private javax.swing.JTextField stepSizeTextField2;
    private javax.swing.JRadioButton visibleEntsRadioButton2;
    private javax.swing.JRadioButton visibleWaypointsRadioButton2;
    private javax.swing.JPanel weaponsjPanel14;
    private javax.swing.JPanel whoKillsWhomjPanel14;
    // End of variables declaration//GEN-END:variables
    private RLBot dbgBot = null;
    private BotStatistic currentStats = null;
    private BotStatistic gameStats = null;
    private BotStatistic loadedStats = null;
    private Vector<MapBotBase> bots = new Vector<MapBotBase>();
    private Vector<GameObject> requiredList = new Vector<GameObject>();
    private DebugStepJob stepJob = null;
    private MainFrameUpdater updater = null;
    private LinkedList<Process> childProcesses = new LinkedList<Process>();
    
    public JTextArea getMessagesTextArea() {
        return messages;
    }

    private void updateBotsList() {
        int lastSelection = connectedBotsList1.getSelectedIndex();

        Vector<MapBotBase> smToDelete = new Vector<MapBotBase>();
        for (MapBotBase b : bots) {
            if (!b.isConnected()) {
                smToDelete.add(b);
            }
        }
        bots.removeAll(smToDelete);

        if (dbgBot != null && !dbgBot.isConnected()) {
            dbgBot = null;
        }

        DefaultListModel m = new DefaultListModel();
        for (MapBotBase b : bots) {
            m.addElement(b);
        }
        if (dbgBot != null) {
            m.addElement(dbgBot);
        }

        connectedBotsList1.setModel(m);
        connectedBotsList1.setSelectedIndex(lastSelection);
        connectedBotsList1ValueChanged(null);
    }

    BotBase getBotFromList(int ind) {
        if (ind < 0 || ind > bots.size() + 1) {
            return null;
        }
        if (ind < bots.size()) {
            return bots.elementAt(ind);
        } else if (ind == bots.size()) {
            return dbgBot;
        }
        return null;
    }

    public void updateDisplayedInfo() {
        if (dbgBot != null && dbgBot.getFrameNumber() > 1) {
            if (visibleWaypointsRadioButton2.isSelected()) {
                visibleWaypointsRadioButton2ActionPerformed(null);
            } else if (allEntsRadioButton1.isSelected()) {
                allEntsRadioButton1ActionPerformed(null);
            } else if (visibleEntsRadioButton2.isSelected()) {
                visibleEntsRadioButton2ActionPerformed(null);
            } else if (navPlanRadioButton.isSelected()) {
                navPlanRadioButtonActionPerformed(null);
            } else if (pickupFailuresRadioButton1.isSelected()) {
                pickupFailuresRadioButton1ActionPerformed(null);
            } else if (edgeFailuresRadioButton.isSelected()) {
                edgeFailuresRadioButtonActionPerformed(null);
            } else if (enemyInfoRadioButton1.isSelected()) {
                enemyInfoRadioButton1ActionPerformed(null);
            }
            reqListValueChanged(null);
            botStateInfoTextArea1.setText(dbgBot.toDetailedString());
            if (currentStats != null) {
                statsInfo.setText(currentStats.statsInfo);
            }
        }

        updateBotsList();
    }

    private void setReqList(Vector<GameObject> vect) {
        int lastSelection = reqList.getSelectedIndex();
        requiredList.clear();
        requiredList.addAll(vect);
        DefaultListModel m = new DefaultListModel();
        for (Object o : requiredList) {
            m.addElement(o);
        }
        reqList.setModel(m);
        reqList.setSelectedIndex(lastSelection);
        fullInfo.setText("");
        reqListValueChanged(null);
    }

    private void setUpdater() {
        if (updater != null) {
            return;
        }
        updater = new MainFrameUpdater(this);
        Thread t = new Thread(updater);
        t.start();
    }
    Date programStartDate = new java.util.Date();

    private String getCurrentMapName() {
        if (dbgBot != null) {
            return dbgBot.getMapName();
        }
        for (MapBotBase b : bots) {
            return b.getMapName();
        }
        return "no game running!";
    }

    private String getStatsDescription() {
        DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm");

        String ret = "date: " + dateFormat.format(programStartDate) + "\n" +
                "map: " + getCurrentMapName() + "\n";

        if (dbgBot != null) {
            ret += "\n" + dbgBot.toDetailedString();
        }
        for (MapBotBase b : bots) {
            ret += "\n" + b.toDetailedString();
        }

        return ret;

    }
}
